#pragma once

#include "curlwork/curlwork.hpp"

namespace curlwork {

template<long O>
struct basic_slist
{
    curl_slist *slist_;

    basic_slist() throw()
        : slist_(0)
    {   }

    template<typename P>
    basic_slist(const P& p)
        : slist_(0)
    {
        error_type e = curl_easy_getinfo(p.handle(),
                                         static_cast<info_type>(O), &slist_);

        if (e != no_error)
            throw std::runtime_error(description(e));
    }

    explicit basic_slist(const char *text) throw()
        : slist_(curl_slist_append(slist_, text))
    {   }

    ~basic_slist() throw()
    {
        reset();
    }

    void add(const char *text) throw()
    {
        slist_ = curl_slist_append(slist_, text);
    }

    std::size_t size() const throw()
    {
        curl_slist *slist = slist_;

        if (slist)
        {
            std::size_t i = 1;
            slist = slist->next;

            while (slist)
            {
                ++i;
                slist = slist->next;
            }
        }

        return 0;
    }

    template<typename F>
    void for_each(F f) const
    {
        curl_slist *slist = slist_;

        while (slist)
        {
            f(slist->data);
            slist = slist->next;
        }
    }

    void reset(const char *text = 0) throw()
    {
        if (slist_)
        {
            curl_slist_free_all(slist_);
            slist_ = 0;
        }

        if (text)
            add(text);
    }

    template<typename P>
    void apply(const P& p) const
    {
        set_option(p.handle(), O, slist_);
    }
};

} // namespace curlwork
